package main

import (
	"flag"
	"fmt"
	"net"
	"net/rpc"
	"net/rpc/jsonrpc"
	"os"
	"src/config"
	"src/log"
	"src/rpcctrl"
	"src/session"
	"src/sessionadmin"
	"time"
)

func init() {
	log.SetPrefix("proxy_server:")
}

//Server 服务器管理块
type Server struct {
	addr                string
	port                int
	rpcPort             int
	transportclientbase int
	transportdevbase    int
	admin               *sessionadmin.Admin
}

func (s *Server) sessionShow() {
	log.Println("*****")
	log.Println("*****")
	log.Println("port=", s.port, "rpcPort=", s.rpcPort)
	log.Println("goto server session show **********************************")
	s.admin.Show()
}

func (s *Server) getInfo(cmd string) string {
	str := ""
	switch cmd {
	case "getinfo":
		str += fmt.Sprintf("port=%d and rpcport=%d\r\n", s.port, s.rpcPort)
		str += fmt.Sprintf("goto server session show **********************************\r\n")
		str += s.admin.GetInfo()
	}

	return str
}

func (s *Server) syncSession() {
	s.admin.SyncSession()
}

func (s *Server) goInitTicker() {
	showTicker := time.NewTicker(5 * time.Second)
	syncTicker := time.NewTicker(5 * time.Second)

	for {
		select {
		case <-showTicker.C:
			//定时显示
			s.sessionShow()
		case <-syncTicker.C:
			//定时同步会话，删除退出状态会话等
			s.syncSession()
		}
	}
}

func (s *Server) goRPCListenInit(ln net.Listener) {
	rpcctrl.RegistCallback("getinfo", s.getInfo)
	rpc.Register(rpcctrl.GetRPCCtrl())

	for {
		conn, err := ln.Accept()
		if err != nil {
			continue
		}

		go func(conn net.Conn) {
			log.Println("new rpc req coming ")
			jsonrpc.ServeConn(conn)
		}(conn)
	}
}

var (
	addr           string
	port           int
	rpcPort        int
	portclientbase int
	portdevbase    int
	h              bool
	outputLogPath  string
)

func usage() {
	fmt.Fprintf(os.Stderr, `proxy_server version: 1.0
	Usage: proxy_server [-h] [-serveraddr "0.0.0.0"] [-serverport 0] [-portclientbase 0] 
	[-portdevbase 0] [-logfile "log"] [-rpcport 6001]
	
	Options:
	`)
	flag.PrintDefaults()
}

func (s *Server) argParse() bool {
	flag.BoolVar(&h, "h", false, "this help")
	flag.StringVar(&addr, "serveraddr", config.ServerListenAddr, "代理服务器地址")
	flag.IntVar(&port, "serverport", config.ServerListenPort, "代理服务器端口")
	flag.IntVar(&rpcPort, "rpcport", config.ServerRPCPort, "rpc服务器监听端口")
	flag.IntVar(&portclientbase, "portclientbase", config.ServerTransPortBaseClient, "客户端连接基础端口")
	flag.IntVar(&portdevbase, "portdevbase", config.ServerTransPortBaseDev, "设备端连接基础端口")
	flag.StringVar(&outputLogPath, "logfile", "", "输出日志文件")
	flag.Usage = usage

	flag.Parse()
	if h {
		flag.Usage()
		return false
	}

	if outputLogPath != "" {
		log.SetOutputPathFile(outputLogPath)
	}
	s.addr = addr
	s.port = port
	s.rpcPort = rpcPort
	s.transportclientbase = portclientbase
	s.transportdevbase = portdevbase

	return true
}

func main() {
	var server Server = Server{
		admin: sessionadmin.GetNewAdmin(),
	}
	//参数解析
	if !server.argParse() {
		return
	}
	//服务器rpc监听端口初始化
	rpcServer := fmt.Sprintf(":%d", server.rpcPort)
	lrpc, errRPC := net.Listen("tcp", rpcServer)
	if errRPC != nil {
		panic(errRPC)
	}
	go server.goRPCListenInit(lrpc)

	//服务器连接监听端口初始化
	dstserver := fmt.Sprintf(":%d", server.port)
	ln, err := net.Listen("tcp", dstserver)
	if err != nil {
		panic(err)
	}
	log.Println("net open successed", ln)

	//开个协程处理周期定时任务
	go server.goInitTicker()
	clientbaseid := server.transportclientbase
	devbaseid := server.transportdevbase
	//服务器程序不打算退出
	for {
		log.Println("accept next:\r\n")
		conn, err := ln.Accept()
		if err != nil {
			log.Println(err)
			continue
		}
		sid := server.admin.GetID()
		if sid < 0 {
			log.Println("session is max limit now !!!!!!!!!!!!!!!!!!!")
			continue
		}

		ses := session.GetNewServerSession(conn, sid, clientbaseid+sid, devbaseid+sid)
		if ses == nil {
			conn.Close()
			continue
		}
		server.admin.AddSession(ses)

		go ses.ConnStart()
	}
}
